# 负责绘制图片内容
import pygame.key
from mygun import MyGun
from console import *
from fish_net import *
from game_rhythm import *
from bomb import *
from music import *


class Painter:
    def __init__(self) -> None:
        """ 游戏素材导入 """
        self.screen = pygame.display.set_mode(BG_SIZE)  # 画布
        self.myGun = MyGun()  # 我方大炮
        self.console = Console()  # 控制台
        self.super_bullet = SuperBullet()  # 超级子弹
        self.bomb = Bomb()  # 炸弹图片
        self.difficulty_leve = DifficultyLevel()  # 难度等级
        self.group_control = GroupControl()  # 控制所有分组
        self.game_control = GameControl()  # 游戏进程控制
        self.highest_score = self.game_control.get_score()

        """ 游戏基础设置 """
        self.bg = pygame.image.load(r'img\bg.png').convert_alpha()  # 背景图片
        # 游戏炸弹图标
        self.bomb_icon = pygame.transform.scale(self.bomb.image,
                                                (self.bomb.rect.width * 0.5, self.bomb.rect.height * 0.5))
        # 超级子弹图标
        self.super_bullet_icon = pygame.transform.scale(self.super_bullet.image,
                                                        (self.super_bullet.rect.width * 0.5,
                                                         self.super_bullet.rect.height * 0.5))
        self.super_bullet_icon = pygame.transform.rotate(self.super_bullet_icon, -90)
        self.running = True  # 程序是否执行
        self.clock = pygame.time.Clock()  # 帧率控制类
        self.delay = 0  # 游戏延时控制
        pygame.display.set_caption(TITLE)  # 标题
        self.my_gun_index = 0
        self.delay = 0
        self.is_pause = False
        # 计时器，每间隔一段时间复活一些鱼
        self.fish_reset_timer = pygame.USEREVENT
        pygame.time.set_timer(self.fish_reset_timer, 5 * 1000)
        # 超级子弹计时器
        self.super_bullet_timer = pygame.USEREVENT + 1
        self.is_super_bullet = False
        # 游戏结束计时器
        self.game_over_timer = pygame.USEREVENT + 2
        self.game_over = GAME_OVER * 1000
        # 游戏开始时间
        self.start_time = 0
        # 游戏运行时间
        self.run_time = 0
        self.old_time = 0
        # 字体
        self.font = pygame.font.Font(r'font/font.ttf', 36)
        # 获取当前场内的鱼
        self.field_fishes = self.group_control.get_field_fishes()
        # 结束音乐判断
        self.end_music = True

    def run(self):
        """ 运行游戏 """
        pygame.mixer.music.play(-1)
        first_fish_dict = {
            'gold_fish': 10,
            'octopus_fish': 5,
            'manta_fish': 5,
            'shark_fish': 3,
            'boss_fish': 1
        }
        self.group_control.add_fish_to_dict(first_fish_dict)
        # 初次处于游戏开始阶段
        self.game_control.game_home_menu()
        while self.running:
            self.field_fishes = self.group_control.get_field_fishes()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    return not self.running
                if event.type == self.fish_reset_timer:
                    # 每间隔一段时间，复活所有的鱼
                    for fish in self.group_control.all_fishes:
                        if not fish.active:
                            fish.reset()
                    pygame.time.set_timer(self.fish_reset_timer, 5 * 1000)
                if event.type == self.super_bullet_timer:
                    # 取消超级子弹
                    self.is_super_bullet = False
                    pygame.time.set_timer(self.super_bullet_timer, 0)
                if event.type == self.game_over_timer:
                    # 游戏结束
                    self.game_control.game_over()
                    pygame.mixer.music.stop()
                    pygame.time.set_timer(self.game_over_timer, 0)
                # 如果用户按下键盘
                if event.type == pygame.KEYDOWN:
                    # 如果用户按下空格，表示需要发射子弹
                    if event.key == pygame.K_SPACE and len(self.group_control.bullets) < 5:
                        bullet_sound.play()
                        # 普通子弹
                        if not self.is_super_bullet:
                            bullet = Bullet()
                            bullet.reset(self.myGun)
                            self.group_control.add_bullet(bullet)
                        # 超级子弹
                        else:
                            super_bullet = SuperBullet()
                            super_bullet.reset(self.myGun)
                            self.group_control.add_bullet(super_bullet)
                    # 表示释放炸弹
                    if event.key == pygame.K_1 and self.bomb.number > 0:
                        bomb_sound.play()
                        self.bomb.number -= 1
                        bomb_text = self.font.render(f' × {self.bomb.number}', True, 'white')
                        self.screen.blit(self.bomb.image, self.bomb.rect)
                        self.screen.blit(bomb_text, (WIDTH - 150, 13))
                        # for fish in self.group_control.all_fishes:
                        for fish in self.field_fishes:
                            fish.life -= 200
                            if fish.life <= 0:
                                if isinstance(fish, MantaFish):
                                    self.myGun.kill_manta += 1
                                elif isinstance(fish, SharkFish):
                                    self.myGun.kill_shark += 1
                                elif isinstance(fish, BossFish):
                                    self.myGun.kill_manta += 1
                                    self.myGun.kill_shark += 1
                                self.myGun.score += fish.kill_score
                                fish.active = False
                # 按下鼠标，判断是否需要暂停/继续
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if self.game_control.rect.collidepoint(event.pos) and not self.game_control.is_game_over \
                            and not self.game_control.is_game_home:
                        if self.game_control.is_pause:
                            self.game_control.game_continue()
                            self.game_over = GAME_OVER * 1000 - self.old_time
                            self.start_time = pygame.time.get_ticks()
                            pygame.time.set_timer(self.game_over_timer, self.game_over)
                            pygame.mixer.music.play(-1)
                        else:
                            self.game_control.game_pause()
                            self.old_time = self.run_time
                            pygame.time.set_timer(self.game_over_timer, 0)
                            pygame.mixer.music.stop()
                    # 判断是否重新开始游戏
                    if self.game_control.is_game_over and self.game_control.regame_btn_rect.collidepoint(event.pos):
                        return self.running
                    # 判断是否结束游戏
                    if (self.game_control.is_game_over or self.game_control.is_game_home) \
                            and self.game_control.game_over_btn_rect.collidepoint(event.pos):

                        return not self.running

                    # 判断是否需要开始游戏
                    if self.game_control.is_game_home and self.game_control.game_start_rect.collidepoint(event.pos):
                        self.game_control.is_game_home = False
                        self.game_control.game_continue()
                        self.start_time = pygame.time.get_ticks()
                        # 开始游戏结束计时
                        pygame.time.set_timer(self.game_over_timer, self.game_over)

            # 更新游戏参数
            self.update()

            # 更新游戏参数后绘画
            self.draw()

            # 控制帧率
            self.clock.tick(FPS)

            # 控制延时
            self.delay = (self.delay + 1) % 200

    # 绘制游戏内容
    def draw(self):
        self.screen.blit(self.bg, (0, 0))  # 背景

        """ 开始菜单界面 """
        if self.game_control.is_game_home:
            # 绘制主菜单背景
            self.screen.blit(self.game_control.image, self.game_control.rect)
            # 历史最高分
            score_text = self.font.render(str(self.highest_score), True, 'red')
            self.game_control.image.blit(score_text, (430, 205))
            # 游戏开始按钮
            self.screen.blit(self.game_control.game_start, self.game_control.game_start_rect)
            # 游戏结束按钮
            self.screen.blit(self.game_control.game_over_btn, self.game_control.game_over_btn_rect)
            pygame.display.flip()
            return

        """ 游戏结束 """
        if self.game_control.is_game_over:
            # 绘制结束背景
            self.screen.blit(self.game_control.image, self.game_control.rect)
            # 分数颜色
            text_color = 'white'
            # 历史最高
            score_text = self.font.render(str(self.highest_score), True, text_color)
            if self.myGun.score > self.highest_score:
                text_color = 'red'

            self.game_control.image.blit(score_text, (410, 267))
            # 当前得分
            score_text = self.font.render(str(self.myGun.score), True, text_color)
            self.game_control.image.blit(score_text, (410, 180))
            # 如果破纪录写入记录，并播放背景音乐
            if text_color == 'red':
                if self.end_music:
                    record_break_sound.play()
                self.game_control.write_score(self.myGun.score)
            elif self.end_music:
                game_over_sound.play()
            self.end_music = False

            # 游戏重来按钮
            self.screen.blit(self.game_control.regame_btn, self.game_control.regame_btn_rect)
            # 游戏结束按钮
            self.screen.blit(self.game_control.game_over_btn, self.game_control.game_over_btn_rect)
            pygame.display.flip()
            return
        self.screen.blit(self.bg, (0, 0))

        """ 游戏暂停/继续的情况 """
        if self.game_control.is_pause:
            self.screen.blit(self.game_control.image, self.game_control.rect)
            pygame.display.flip()
            return
        else:
            self.screen.blit(self.game_control.image, self.game_control.rect)

        """ 游戏时间 """
        curr_time = self.font.render(f'当前用时 {self.run_time // 1000} s', True, 'white')
        self.screen.blit(curr_time, (WIDTH - curr_time.get_width() - 10, 70))
        game_all_time = self.font.render(f'游戏总时长 {GAME_OVER} s', True, 'white')
        self.screen.blit(game_all_time, (10, 70))

        """ 绘制所有活着的鱼 """
        for fish in self.group_control.all_fishes:
            if fish.active:
                self.screen.blit(fish.image, fish.rect)

        """ 绘制所有子弹 """
        for bullet in self.group_control.bullets:
            if bullet.active:
                self.screen.blit(bullet.image, bullet.rect)

        """ 绘制所有的渔网 """
        for fish_net in self.group_control.fish_nets:
            self.screen.blit(fish_net.image, fish_net.rect)

        """ 绘制分数 """
        score_text = self.font.render(f'得分：{self.myGun.score}', True, 'white')
        self.screen.blit(score_text, (10, 10))

        """ 绘制炸弹图标 """
        bomb_text = self.font.render(f' × {self.bomb.number}', True, 'white')
        self.screen.blit(self.bomb.image, self.bomb.rect)
        self.screen.blit(bomb_text, (WIDTH - 150, 13))

        self.screen.blit(self.console.image, self.console.img_rect)  # 控制台

        """ 绘制能量条底纹 """
        pygame.draw.line(self.screen, '#88fffd', (self.console.img_rect.left + 40, self.console.img_rect.top - 3),
                         (self.console.img_rect.right - 40, self.console.img_rect.top - 3), 5)
        self.screen.blit(self.bomb_icon,
                         (self.console.img_rect.left + 35, self.console.img_rect.top - self.bomb_icon.get_height() + 3))

        pygame.draw.line(self.screen, '#a9aaf4', (self.console.img_rect.left + 40, self.console.img_rect.bottom + 3),
                         (self.console.img_rect.right - 40, self.console.img_rect.bottom + 3), 5)
        self.screen.blit(self.super_bullet_icon, (self.console.img_rect.left + 15, self.console.img_rect.bottom - 10))

        """ 绘制炸弹能量条充能条纹 """
        energy_bomb = self.myGun.kill_manta / KILL_MANTA_TO_BOMB
        energy_color = '#f2b305' if energy_bomb < 0.7 else '#f30d33'

        if energy_bomb != 0:
            pygame.draw.line(self.screen, energy_color,
                             (self.console.img_rect.right - (self.console.img_rect.width * energy_bomb),
                              self.console.img_rect.top - 3),
                             (self.console.img_rect.right - 40, self.console.img_rect.top - 3), 5)

        """ 绘制超级子弹能量条充能条纹 """
        energy_super_bullet = self.myGun.kill_shark / KILL_SHARK_TO_SUPER
        energy_color = '#e4571a' if energy_super_bullet < 0.7 else '#f30d33'

        if energy_super_bullet != 0:
            pygame.draw.line(self.screen, energy_color,
                             (self.console.img_rect.right - (self.console.img_rect.width * energy_super_bullet),
                              self.console.img_rect.bottom + 3),
                             (self.console.img_rect.right - 40, self.console.img_rect.bottom + 3), 5)

        self.screen.blit(self.myGun.image, self.myGun.img_rect)  # 我方大炮

        pygame.display.flip()

    # 游戏参数更新
    def update(self):
        if self.game_control.is_pause or self.game_control.is_game_over or self.game_control.is_game_home:
            return

        """ 更新当前游戏时间"""
        self.run_time = pygame.time.get_ticks() - self.start_time + self.old_time

        # 根据键盘事件，判断是否需要旋转，delay表示延时，是否需要切换到一帧动画
        self.myGun.update(keys=pygame.key.get_pressed(), delay=self.delay)

        """ 更新所有活着的鱼的位置 """
        for fish in self.group_control.all_fishes:
            if fish.active:
                fish.update(self.delay)

        """ 更新所有子弹的位置 """
        for bullet in self.group_control.bullets:
            if bullet.active:
                bullet.update()
                if bullet.collision(self.field_fishes):
                    fish_net = FishingNet() if not bullet.is_super else SuperFishingNet()
                    fish_net.reset(bullet)
                    self.group_control.add_fish_net(fish_net)
            else:
                self.group_control.bullets.remove(bullet)

        """ 判断是否渔网是否捕捉到了鱼，并且没间隔40帧就清除死亡的渔网 """
        for fish_net in self.group_control.fish_nets:
            res = fish_net.collision(self.field_fishes)
            self.myGun.score += res['score']
            self.myGun.kill_manta += res['kill_manta'] + res['kill_boss'] * 2
            self.myGun.kill_shark += res['kill_shark'] + res['kill_boss'] * 2
            if self.delay % 40 == 0:
                self.group_control.fish_nets.remove(fish_net)
                self.delay = 0

        """ 判断是否可以给予奖励(炸弹和超级子弹) """
        if self.myGun.kill_manta >= KILL_MANTA_TO_BOMB:
            supply_sound.play()
            self.bomb.number += 1
            self.myGun.kill_manta = 0

        if self.myGun.kill_shark >= KILL_SHARK_TO_SUPER:
            supply_sound.play()
            self.is_super_bullet = True
            # 重置计时器
            pygame.time.set_timer(self.super_bullet_timer, 0)
            # 开始计时
            pygame.time.set_timer(self.super_bullet_timer, SUPER_BULLET_TIME * 1000)
            self.myGun.kill_shark = 0

        """ 根据难度等级增加难度 """
        self.difficulty_leve.set_level(self.myGun.score, self.group_control)
